#include "manager.h"

#include "spriteFactory.h"
#include "multiSpriteFactory.h"
#include "explosionFactory.h"
#include "bossPuppetController.h"

#include "SDL/SDL_gfxPrimitives.h"

Manager::~Manager()
{
	if(!restart)
	{
		delete SpriteFrameFactory::getInstance();
		delete MultiSpriteFrameFactory::getInstance();
		delete ExplosionFrameFactory::getInstance();
		delete &Gamedata::getInstance();
	}
	else
	{
		spriteManager.restart();
		simulator.restart();
	}
}

Manager::Manager() :
	env( SDL_putenv(const_cast<char*>("SDL_VIDEO_CENTERED=center")) ),
	restart(false),
	gdata( Gamedata::getInstance() ),
	io( IOManager::getInstance() ),
	clock( Clock::getInstance() ),
	sound( SDLSound::getInstance()),
	screen( io.getScreen() ),
	player("player"),
	boss("boss"),
	worldSky("sky", 6),
	worldClouds("clouds", 4),
	worldTrees("trees", 2),
	worldGrass("grass"),
	worldFlowers("flowers"),
	view(Viewport::getInstance()),
	hud(),
	startMenu(),
	midMenu(),
	endMenu(),
	spriteManager(SpriteManager::getInstance()),
	simulator(Simulator::getInstance()),
	startTime(0)
{
	if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0) {
		throw string("Unable to initialize SDL: ");
	}
	view.setObjectToTrack(player.getSprite());
	atexit(SDL_Quit);

	spriteManager.setPlayer(&player);
	spriteManager.setBoss(&boss);
	simulator.setPlayer(&player);

	spriteManager.addPuppetController(new BossPuppetController(&player, &boss));
	hud.setPlayer(&player);
	simulator.setContactListener(static_cast<ContactListener *>(&spriteManager));

	startMenu.addButton("start");
	startMenu.addButton("toggle");
	startMenu.addButton("quit");

	midMenu.addButton("restart");
	midMenu.addButton("toggle");
	midMenu.addButton("quit");

	endMenu.addButton("restart");
	endMenu.addButton("quit");
}

void Manager::end()
{
  SDL_Event event;
  bool menuDone = false;
  bool keyCatch = false;
  char msg[1024];
  Sprite gameover("gameover");
  Vector2f pos = gameover.getPosition();
  gameover.setPosition(Vector2f(pos[0] + view.X(), pos[1] + view.Y()));

	int sec_elapsed = clock.getSeconds() - startTime;
	int score = player.getScore();
	int accum = 0;
	if(boss.isDead())
		accum += (score - sec_elapsed) * 10;
	if(!player.didJump())
		accum += score * 4;
	if(player.getShotsFired() > 0)
		accum += 1000 * (player.getShotsHit() / player.getShotsFired());
	score += accum -sec_elapsed;
	sprintf(msg, "Score: %d", score);

  while (menuDone != true) {
    worldSky.draw();
    worldClouds.draw();
    worldTrees.draw();
    worldGrass.draw();
    player.draw();
    worldFlowers.draw();
    spriteManager.draw();
    view.draw();
    hud.draw();
    boxRGBA(screen, 0, 0, view.getViewWidth(), view.getViewHeight(), 0, 0, 0,100);
    endMenu.draw();
    gameover.draw();

	boxRGBA(screen,0,260,screen->w,300,255,255,255,255);
    io.printMessageCenteredAt(msg, 270);
    

    SDL_Flip(screen);
    
    SDL_PollEvent(&event);
    boxRGBA(screen, 0, 0, view.getViewWidth(), view.getViewHeight(), 0, 0, 0,100);
    //Handle menu keys
    if (event.type ==  SDL_QUIT) { break; }
    if(event.type == SDL_KEYUP) { keyCatch = false; }
    if(event.type == SDL_KEYDOWN) {
      switch ( event.key.keysym.sym ) {
		  cout << "switch" << endl;
        case SDLK_ESCAPE : menuDone = true; break;
        case SDLK_q      : menuDone = true; break;
		case SDLK_RETURN : {
		  if ( !keyCatch ) {
			keyCatch = true;
		    	endMenu.lightOn();
			if(endMenu.getIconClicked() == "restart") {
				menuDone = true;
				restart = true;
			}
			else if(endMenu.getIconClicked() == "quit"){
				menuDone = true;
			}
			cout << "Chosen: " << endMenu.getIconClicked() << endl;
			break;
		  }
		}
        //menu movement down
        case SDLK_DOWN   : {
          if ( !keyCatch ) {
	    keyCatch = true;
            endMenu.increment();
          }
          break;
        }
        //menu movement up
        case SDLK_UP   : {
          if ( !keyCatch ) {
	    keyCatch = true;
            endMenu.decrement();
          }
          break;
        }
        default : break;
      }
    }
    if(event.type == SDL_KEYUP) {
      keyCatch = false; 
      endMenu.lightOff();
    }
  }
}

bool Manager::menu()
{
  SDL_Event event;
  bool menuDone = false;
  bool done = false;
  bool keyCatch = false;

  sound.setMusic("sounds/music/Urban-Ruins.mp3");

  while (menuDone != true) {
    worldSky.draw();
    worldClouds.draw();
    worldTrees.draw();
    worldGrass.draw();
    player.draw();
    worldFlowers.draw();
    spriteManager.draw();
    view.draw();
    boxRGBA(screen, 0, 0, view.getViewWidth(), view.getViewHeight(), 0, 0, 0,100);		
    midMenu.draw();    
    
    SDL_Flip(screen);
    
    SDL_PollEvent(&event);
    
    //Handle menu keys
    if (event.type ==  SDL_QUIT) { break; }
    if(event.type == SDL_KEYUP) { keyCatch = false; }
    if(event.type == SDL_KEYDOWN) {
      switch ( event.key.keysym.sym ) {
        case SDLK_ESCAPE : menuDone = true; done = true; break;	
        case SDLK_q      : menuDone = true; done = true; break;
		case SDLK_RETURN : {
		  if ( !keyCatch ) {
			keyCatch = true;
		    	midMenu.lightOn();
			if(midMenu.getIconClicked() == "toggle") {
				sound.toggleMusic();
			}
			else if(midMenu.getIconClicked() == "quit"){
				menuDone = true;
				done = true;
			}
			else if(midMenu.getIconClicked() == "restart"){
				menuDone = true;
				done = true;
				restart = true;
			}
			cout << "Chosen: " << midMenu.getIconClicked() << endl;
			break;
		  }
		}
        //menu movement down
        case SDLK_DOWN   : {
          if ( !keyCatch ) {
	    keyCatch = true;
            midMenu.increment();
          }
          break;
        }
        //menu movement up
        case SDLK_UP   : {
          if ( !keyCatch ) {
	    keyCatch = true;
            midMenu.decrement();
          }
          break;
        }
        //menu continue
        case SDLK_m   : {
          if ( !keyCatch ) {
	    keyCatch = true;
            menuDone = true;
          }
          break;
        }
        default : break;
      }
    }
    if(event.type == SDL_KEYUP) {
      keyCatch = false; 
      midMenu.lightOff();
    }
  }
  return done;	
}

bool Manager::start()
{
  SDL_Event event;
  bool menuDone = false;
  bool done = false;
  bool keyCatch = false;
  //menu loop

  sound.setMusic("sounds/music/Urban-Ruins.mp3");

  while (menuDone != true) {
    worldSky.draw();
    worldClouds.draw();
    worldTrees.draw();
    worldGrass.draw();
    player.draw();
    worldFlowers.draw();
    spriteManager.draw();
    view.draw();
    boxRGBA(screen, 0, 0, view.getViewWidth(), view.getViewHeight(), 0, 0, 0,100);		
    startMenu.draw();    
    
    SDL_Flip(screen);
    
    SDL_PollEvent(&event);
    
    //Handle menu keys
    if (event.type ==  SDL_QUIT) { break; }
    if(event.type == SDL_KEYUP) { keyCatch = false; }
    if(event.type == SDL_KEYDOWN) {
      switch ( event.key.keysym.sym ) {
        case SDLK_ESCAPE : menuDone = true; done = true; break;	
        case SDLK_q      : menuDone = true; done = true; break;
		case SDLK_RETURN : {
		  if ( !keyCatch ) {
			keyCatch = true;
		    	startMenu.lightOn();
			if(startMenu.getIconClicked() == "start") {
				menuDone = true;
			}
			else if(startMenu.getIconClicked() == "toggle") {
				sound.toggleMusic();
			}
			else if(startMenu.getIconClicked() == "quit"){
				menuDone = true;
				done = true;
			}
			cout << "Chosen: " << startMenu.getIconClicked() << endl;
			break;
		  }
		}
        //menu movement down
        case SDLK_DOWN   : {
          if ( !keyCatch ) {
	    keyCatch = true;
            startMenu.increment();
          }
          break;
        }
        //menu movement up
        case SDLK_UP   : {
          if ( !keyCatch ) {
	    keyCatch = true;
            startMenu.decrement();
          }
          break;
        }
        default : break;
      }
    }
    if(event.type == SDL_KEYUP) {
      keyCatch = false; 
      startMenu.lightOff();
    }
  }
  return done;	
}

void Manager::play()
{
	SDL_Event event;

	bool done = false;
	bool keyCatch = false;

	if(Manager::start())
		done = true;

	sound.setMusic("sounds/music/CHS-ZeldaMidnas-Smi.mp3");
	startTime = clock.getSeconds();

	SDL_EnableKeyRepeat(0,SDL_DEFAULT_REPEAT_INTERVAL);
	SDL_ShowCursor(SDL_DISABLE);
	while ( not done ) {
		worldSky.draw();
		worldClouds.draw();
		worldTrees.draw();
		worldGrass.draw();
		player.draw();
		boss.draw();
		worldFlowers.draw();
		spriteManager.draw();
		view.draw();
		hud.draw();

		Uint32 ticks = clock.getElapsedTicks();

		spriteManager.update(ticks);
		view.update();
		worldSky.update();
		worldClouds.update();
		worldTrees.update();
		worldGrass.update();
		worldFlowers.update();
		hud.update(clock.getFps());

		SDL_Flip(screen);

		while(SDL_PollEvent(&event)) {
			if( event.type == SDL_MOUSEMOTION ) {
				player.handleMouseMotion();
			}
			else if(event.type == SDL_MOUSEBUTTONDOWN) {
				if(event.button.button == SDL_BUTTON_LEFT) {
					player.shoot();
				}
				else if(event.button.button == SDL_BUTTON_RIGHT) {
					player.attachGrapple();
				}
			}
			else if(event.type == SDL_MOUSEBUTTONUP) {
				if(event.button.button == SDL_BUTTON_RIGHT) {
					player.releaseGrapple();
				}
			}
			else if(event.type == SDL_USEREVENT) {
				switch ( event.user.code ) {
					case EVENT_SPAWN_ITEM:
						sound[3];
						spriteManager.addItemPickup(*(Vector2f *)event.user.data1);
						break;
					case EVENT_PLAYER_DEAD:
						view.setObjectToTrack(boss.getSprite());
						break;
					case EVENT_GAME_OVER:
						//TODO: display game over menu
						Manager::end(); done = true;
						break;
					default:
						break;
				}
			}
			else if(event.type ==  SDL_QUIT) { done = true; restart = false; break; }
			else if(event.type == SDL_KEYUP) {
				keyCatch = false;
				switch ( event.key.keysym.sym ) {
					default: break;
				}
			}
			else if(event.type == SDL_KEYDOWN) {
				switch ( event.key.keysym.sym ) {
					// Player controls
					case SDLK_w      : player.jump(); break;
					case SDLK_a      : player.left(); break;
					case SDLK_s      : break;
					case SDLK_d      : player.right(); break;
					case SDLK_SPACE  : player.jump(); break;
					// Other Controls
					case SDLK_ESCAPE : done = true; restart = false; break;
					case SDLK_q      : done = true; restart = false; break;
					case SDLK_TAB    : hud.toggle(); break;
					case SDLK_m      : if(Manager::menu()) done = true; sound.setMusic("sounds/music/CHS-ZeldaMidnas-Smi.mp3"); break;
					case SDLK_MINUS  : --sound; break;
					case SDLK_EQUALS : ++sound; break;
					case SDLK_c      : view.setObjectToTrack(player.getSprite()); break;
					case SDLK_g      : player.toggleGodMode();
					default          : break;
				}
			}
		}
		Uint8 *keystate = SDL_GetKeyState(NULL);
		if(keystate[SDLK_a])
			player.left();
		if(keystate[SDLK_d])
			player.right();
		clock++;
	}
}
